const Koa = require('koa');
const Router = require('@koa/router')
const StaticServer = require('koa-static-server');
const bodyparser = require('koa-body');
const path = require('path');
const cors = require('koa2-cors');
const util = require('./src/util');
const generate = require('./src/generate');
const pdfKit = require('./src/pdf-kit');
const fse = require('fs-extra');
const fs = require("fs");
const mkdirp = require('mkdirp');
const { S3Client, GetObjectCommand } = require("@aws-sdk/client-s3");
const profile = require('./profile')
console.log(profile)
const REGION = profile.REGION;
const bucketName = profile.bucketName;
const fileS3Path = profile.fileS3Path;

const port = process.env.PORT || 8080;
const rootPath = process.env.ROOT_PATH || '/pdf-service';
const readPath = '/read';
const basePath = path.join(rootPath, readPath);

const app = new Koa();
const router = new Router({
    prefix: rootPath
});

// 转换PDF
router.post('/generatePDF', async (ctx) => {
    const {body, headers} = ctx.request;

    util.validateGeneratePdfParam(body);

    const data = [];
    const {pages, ...globalOption} = body;
    const requests = [];
    const type = 1;
    for (let i = 0; i < pages.length; i++) {
        const page = pages[i];
        let promise;
        if (typeof page === 'string') {
            const url = page;
            // 通过普通url生成pdf
            promise = generate({...headers, url, ...globalOption}, null, type);
        } else if (page && typeof page === 'object') {
            // 通过一个完整的配置生成pdf
            const {pdfOption, ...otherCusOption} = page;
            promise = generate({...headers, ...globalOption, ...otherCusOption}, pdfOption, type);
        }
        requests.push(promise);
    }
    try {
        const pdfResults = await Promise.all(requests);
        pdfResults.forEach(pdfPath => {
            data.push(path.join(basePath, pdfPath));
        })
    } catch (e) {
        throw `访问链接时发生了错误：${String(e.message || e)}`;
    }

    ctx.body = {code: 0, data};
});

// 生成图片
router.post('/generateIMG', async (ctx) => {
    const {body, headers} = ctx.request;

    util.validateGenerateImgParam(body);

    const data = [];
    const {pages, ...globalOption} = body;
    const requests = [];
    const type = 2;
    for (let i = 0; i < pages.length; i++) {
        const page = pages[i];
        let promise;
        if (typeof page === 'string') {
            const url = page;
            promise = generate({...headers, url, ...globalOption}, null, type);
        } else if (page && typeof page === 'object') {
            const {imgOption, ...otherOption} = page;
            promise = generate({...headers, ...globalOption, ...otherOption}, imgOption, type);
        }
        requests.push(promise);
    }
    try {
        const imgResults = await Promise.all(requests);
        imgResults.forEach(imgPath => {
            data.push(path.join(basePath, imgPath));
        })
    } catch (e) {
        throw `访问链接时发生了错误：${String(e.message || e)}`;
    }

    ctx.body = {code: 0, data};
});

router.post('/mergePDF', async (ctx) => {
    const {body} = ctx.request;
    util.validateMergePdfParam(body);
    const filePath = await pdfKit.mergesPdf(body, basePath)
    ctx.body = {
        code: 0,
        data: path.join(basePath, filePath),
    };
});

router.post('/splitPDF', async (ctx) => {
    const {body} = ctx.request;
    util.validateSplitPdfParam(body);
    const paths = await pdfKit.splitsPdf(body, basePath)
    ctx.body = {
        code: 0,
        data: paths.map(p => path.join(basePath, p))
    };
});

// 添加pdf 到 pdf-service 托管
router.post('/putPDF', async (ctx) => {
    const {file} = ctx.request.files;

    console.log('[putPDF] path', file.path);

    const filePath = util.generatePath();
    const outputFilePath = path.resolve(util.generateBasePath, filePath)
    await fse.copy(file.path, outputFilePath);

    ctx.body = {
        code: 0,
        data: path.join(basePath, filePath)
    };
});

router.get('/env', async (ctx) => {
    ctx.body = {
        code: 0,
        data: {
            GENERATE_PATH: process.env.GENERATE_PATH || '',
            PORT: port,
            ROOT_PATH: rootPath,
            HOME: process.env.HOME || process.env.USERPROFILE
        }
    };
});

app.use(cors());

function wait(ms) {
    return new Promise(resolve => setTimeout(() =>resolve(), ms));
};

app.use(async (ctx, next) => {

    try {
        let basePath = rootPath+readPath;
        if (ctx.request.url.startsWith(basePath)) {
            // s3下载文件写入当前宿主机目录
            let fileName = ctx.request.url.replace(basePath, "");
            // const REGION = "cn-northwest-1";
            const s3 = new S3Client({region: REGION});
            // Set the bucket parameters
            // const bucketName = "iplus-aws-test-bucket";
            // const fileS3Path = 'filesvr/pdf-generate';

            let key = fileS3Path + fileName;

            let filePath = util.generateBasePath + fileName;
            let array = filePath.replace("//", "/").split('/');
            let filePathDir = filePath.replace(array[array.length-1], "");
            const bucketParams = {
                Bucket: bucketName,
                Key: key,
            };
               const run = async () => {
                try {
                    const streamToString = (stream) =>
                        new Promise((resolve, reject) => {
                            const chunks = [];
                            stream.on("data", (chunk) => chunks.push(chunk));
                            stream.on("error", reject);
                            stream.on("end", () => resolve(Buffer.concat(chunks)));
                        });
                    const data = await s3.send(new GetObjectCommand(bucketParams));
                    const bodyContents = await streamToString(data.Body);
                    //判断文件是否存在
                    await fs.exists(filePath, function (exists) {
                        if (!exists) {
                            mkdirp(filePathDir, (err) => {
                                let writerStream = fs.createWriteStream(filePath);
                                writerStream.write(bodyContents, 'UTF8');
                                writerStream.end();
                            })
                        }
                    });
                } catch (err) {
                    ctx.body = {code: 1, msg: err};
                }
              };
              await run();
              await wait(1000);
        }
         await next();
    } catch (e) {
        // 如果发生异常，转换成统一接口
        console.log(e.message)
        ctx.body = {code: 1, msg: String(e.message || e)};
    }
});

app.use(bodyparser({multipart: true}));

// 路由
app.use(router.routes());

app.use(StaticServer({
    rootDir: util.generateBasePath,
    rootPath: rootPath + readPath
}))

// 静态文件处理
app.use(StaticServer({
    rootDir: './assets',
    rootPath
}))

app.listen(port, function () {
    console.log(`service start in http://127.0.0.1:${port}${rootPath}`);
});
